/*

    tools23d - tools for converting images to 3D formats.
    Copyright (C) 2014  Dave Gorst

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

*/

/**
 * @file   image-calc.c
 * @brief  Image processing size and position calculation functions.
 *
 * This file contains non-backend specific functions for calculating sizes and positions within images.
 */

#include <stdio.h>

#include <FreeImage.h>
#include "tools23d.h"

#ifdef BUILD_BTIME
	#include "btime23d.h"
#else
	#include "photo23d.h"
#endif

#include "image-fi.h"
#include "image.h"
#include "image-calc.h"

/**
Gives new picture height after cropping to 16:9.

@param	input_width	Width of input image
@param	input_height	Height of input image
@return New height after cropping to 16:9.
*/

unsigned int T3D_CalculateCropToWS (unsigned int input_width, unsigned int input_height)
{
	double new_height = (double) input_width;

	new_height /= 16;

	new_height *= 9;

	return (unsigned int) new_height > input_height ? input_height : (unsigned int) new_height;
}

/**
Gives the amount around the edge of the picture to chop off when zooming in to the picture, and returns the new size after zooming.

@param	zoom_percentage	Zoom percentage (200% gives a picture twice the width and height of the original)
@param	width			Pointer to width of image
@param	height			Pointer to height of image
@param	border_width		Pointer to the number of pixels to chop off the left and right sides of the image
@param	border_height		Pointer to the number of pixels to chop off the top and bottom of the image
*/

void T3D_CalculateZoomBorders (unsigned int zoom_percentage, unsigned int * width, unsigned int * height, int * border_width, int * border_height)
{
	double zoom_multiplier = (double) zoom_percentage / 100;
	unsigned int previous_width = *width;
	unsigned int previous_height = *height;
	double new_width = (double) *width;
	double new_height = (double) *height;

	new_width *= zoom_multiplier;
	new_height *= zoom_multiplier;

	if (zoom_percentage > 100)
	{
		/* If the border size is negative this is how much needs to be removed from the outside of the image in order for it to fit the target. */
		*border_width = (int) 0 - ((previous_width - (int) new_width) / 2);
		*border_height = (int) 0 - ((previous_height - (int) new_height) / 2);
	}
	else
	{
		/* If the border size is positive this is how much needs to be removed from the outside of the image in order for it to fit the target. */
		*border_width = (int) ((previous_width - (int) new_width) / 2);
		*border_height = (int) ((previous_height - (int) new_height) / 2);
	}

	*width = (unsigned int) new_width;
	*height = (unsigned int) new_height;
}

/**
Calculate the size of the output left/right images.

@param	picture_mode	Picture output mode (Side-By-Side, Over-and-Under et al)
@param	preserve_ar	Boolean indicating whether we should preserve the aspect ratio of the initial input file rather than stretch to take up as much of the output window as possible
@param	input_width	Width of input left/right image
@param	input_height	Height of input left/right image
@param	target_width	Width of target combined image
@param	target_height	Height of target combined image
@param	output_width	Pointer used to return new width value
@param	output_height	Pointer used to return new height value
*/

void T3D_CalculateOutputSize
(
        Mode picture_mode,
        BOOL preserve_ar,
        unsigned int input_width,
        unsigned int input_height,
        unsigned int target_width,
        unsigned int target_height,
        unsigned int * output_width,
        unsigned int * output_height
)
{
	double input_aspect_ratio;
	double target_aspect_ratio;

	if (picture_mode == FHD3D)
	{
		target_height = 1080;
		target_width = 1920;
	}

	if (picture_mode == FSBS)
	{
		target_width /= 2;
	}

	input_aspect_ratio = (double) input_height / (double) input_width;
	target_aspect_ratio = (double) target_height / (double) target_width;

	*output_width = target_width;
	*output_height = target_height;

	if (preserve_ar)
	{
		if (input_aspect_ratio > target_aspect_ratio)
		{
			/* Use all vertical space */

			*output_width = (unsigned int) ((double) *output_width * input_aspect_ratio);
		}
		else
		{
			/* Use all horizontal space */

			*output_height = (unsigned int) ((double) *output_width * input_aspect_ratio);
		}
	}

	/* This should be done after preserving aspect ratio, as any changes here will be automatically reversed by the TV. */

	switch (picture_mode)
	{
		case OU:
			*output_height /= 2;
		    break;
		case FHD3D:
		case FSBS:
			break;
		case HSBS:
		default:
			*output_width /= 2;
			break;
	}
}


/**
Calculate the positions in the output image that the scaled left and right images should be written to.

@param	picture_mode	Picture output mode (Side-By-Side, Over-and-Under et al)
@param	target_details	Pointer to a structure containing details of the output image
@param	output_width	Desired width of output left/right image
@param 	output_height	Desired height of output left/right image
@param	left_x		Pointer used to return the X position where the left image will be written
@param	left_y		Pointer used to return the Y position where the left image will be written
@param	right_x		Pointer used to return the X position where the right image will be written
@param	right_y		Pointer used to return the Y position where the right image will be written
*/

void T3D_CalculateWritePosition
(
	Mode picture_mode,
	image_details * target_details,
	unsigned int output_width,
	unsigned int output_height,
	unsigned int * left_x,
	unsigned int * left_y,
	unsigned int * right_x,
	unsigned int * right_y
)
{
	/* TODO - fix and test for when image is taller than wide esp. for FHD3D. */

	switch (picture_mode)
	{
	case OU:
		*left_x = ((target_details->width / 2) - (output_width / 2));
		*left_y = (target_details->height / 4) - (output_height / 2);
		*right_x = ((target_details->width / 2) - (output_width / 2));
		*right_y = ((target_details->height / 4) * 3) - (output_height / 2);
		break;
	case FHD3D:
		*left_x = ((target_details->width / 2) - (output_width / 2));
		*left_y = (540 - (output_height / 2));
		*right_x = ((target_details->width / 2) - (output_width / 2));
		*right_y = (1620 + FHD3D_SEPARATOR_BAND - (output_height / 2));
		break;
	case FSBS:
	case HSBS:
	default:
		*left_x = ((target_details->width / 4) - (output_width / 2));
		*left_y = ((target_details->height / 2) - (output_height / 2));
		*right_x = ((target_details->width / 4) * 3) - (output_width / 2);
		*right_y = (target_details->height / 2) - (output_height / 2);
		break;
	}
}

